﻿using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Input;
using XamlInspector.Foundation;
using XamlInspector.Model;

namespace XamlInspector.Services
{
    public class EventService
    {
        private XamlElement _element;
        public event EventHandler<EventArgs<XamlEvent>> EventOccured;

        public void StartMonitoring(XamlElement element)
        {
            _element = element;

            var uiElement = element.Element as UIElement;
            if (uiElement != null)
            {
                uiElement.DoubleTapped += UiElementOnDoubleTapped;
                uiElement.DragEnter += UiElementOnDragEnter;
                uiElement.DragLeave += UiElementOnDragLeave;
                uiElement.DragOver += UiElementOnDragOver;
                uiElement.Drop += UiElementOnDrop;
                uiElement.Holding += UiElementOnHolding;
                uiElement.KeyDown += UiElementOnKeyDown;
                uiElement.KeyUp += UiElementOnKeyUp;
                uiElement.ManipulationCompleted += UiElementOnManipulationCompleted;
                uiElement.ManipulationDelta += UiElementOnManipulationDelta;
                uiElement.ManipulationInertiaStarting += UiElementOnManipulationInertiaStarting;
                uiElement.ManipulationStarted += UiElementOnManipulationStarted;
                uiElement.ManipulationStarting += UiElementOnManipulationStarting;
                uiElement.PointerCanceled += UiElementOnPointerCanceled;
                uiElement.PointerCaptureLost += UiElementOnPointerCaptureLost;
                uiElement.PointerEntered += UiElementOnPointerEntered;
                uiElement.PointerExited += UiElementOnPointerExited;
                uiElement.PointerMoved += UiElementOnPointerMoved;
                uiElement.PointerPressed += UiElementOnPointerPressed;
                uiElement.PointerReleased += UiElementOnPointerReleased;
                uiElement.PointerWheelChanged += UiElementOnPointerWheelChanged;
                uiElement.RightTapped += UiElementOnRightTapped;
                uiElement.Tapped += UiElementOnTapped;
            }
        }

        public void StopMonitoring(XamlElement element)
        {
            if (element == null)
            {
                return;
            }

            var uiElement = element.Element as UIElement;
            if (uiElement != null)
            {
                uiElement.DoubleTapped -= UiElementOnDoubleTapped;
                uiElement.DragEnter -= UiElementOnDragEnter;
                uiElement.DragLeave -= UiElementOnDragLeave;
                uiElement.DragOver -= UiElementOnDragOver;
                uiElement.Drop -= UiElementOnDrop;
                uiElement.Holding -= UiElementOnHolding;
                uiElement.KeyDown -= UiElementOnKeyDown;
                uiElement.KeyUp -= UiElementOnKeyUp;
                uiElement.ManipulationCompleted -= UiElementOnManipulationCompleted;
                uiElement.ManipulationDelta -= UiElementOnManipulationDelta;
                uiElement.ManipulationInertiaStarting -= UiElementOnManipulationInertiaStarting;
                uiElement.ManipulationStarted -= UiElementOnManipulationStarted;
                uiElement.ManipulationStarting -= UiElementOnManipulationStarting;
                uiElement.PointerCanceled -= UiElementOnPointerCanceled;
                uiElement.PointerCaptureLost -= UiElementOnPointerCaptureLost;
                uiElement.PointerEntered -= UiElementOnPointerEntered;
                uiElement.PointerExited -= UiElementOnPointerExited;
                uiElement.PointerMoved -= UiElementOnPointerMoved;
                uiElement.PointerPressed -= UiElementOnPointerPressed;
                uiElement.PointerReleased -= UiElementOnPointerReleased;
                uiElement.PointerWheelChanged -= UiElementOnPointerWheelChanged;
                uiElement.RightTapped -= UiElementOnRightTapped;
                uiElement.Tapped -= UiElementOnTapped;
            }
        }

        private void UiElementOnDoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("DoubleTapped", _element, string.Format("{0}, {1}", e.GetPosition(_element.Element), e.PointerDeviceType)));
        }

        private void UiElementOnTapped(object sender, TappedRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("Tapped", _element, string.Format("{0}, {1}", e.GetPosition(_element.Element), e.PointerDeviceType)));
        }

        private void UiElementOnRightTapped(object sender, RightTappedRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("RightTapped", _element, string.Format("{0}, {1}", e.GetPosition(_element.Element), e.PointerDeviceType)));
        }

        private void UiElementOnPointerWheelChanged(object sender, PointerRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("PointerWheelChanged", _element, string.Format("{0}, {1}", e.GetCurrentPoint(_element.Element).Position, e.GetIntermediatePoints(_element.Element))));
        }

        private void UiElementOnPointerReleased(object sender, PointerRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("PointerReleased", _element, string.Format("{0}, {1}", e.GetCurrentPoint(_element.Element).Position, e.Pointer.PointerDeviceType)));
        }

        private void UiElementOnPointerPressed(object sender, PointerRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("PointerPressed", _element, string.Format("{0}, {1}", e.GetCurrentPoint(_element.Element).Position, e.Pointer.PointerDeviceType)));
        }

        private void UiElementOnPointerMoved(object sender, PointerRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("PointerMoved", _element, string.Format("{0}, {1}", e.GetCurrentPoint(_element.Element).Position, e.Pointer.PointerDeviceType)));
        }

        private void UiElementOnPointerExited(object sender, PointerRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("PointerExited", _element, string.Format("{0}, {1}", e.GetCurrentPoint(_element.Element).Position, e.Pointer.PointerDeviceType)));
        }

        private void UiElementOnPointerCaptureLost(object sender, PointerRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("PointerCaptureLost", _element, string.Format("{0}, {1}", e.GetCurrentPoint(_element.Element).Position, e.Pointer.PointerDeviceType)));
        }

        private void UiElementOnPointerCanceled(object sender, PointerRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("PointerCanceled", _element, string.Format("{0}, {1}", e.GetCurrentPoint(_element.Element).Position, e.Pointer.PointerDeviceType)));
        }

        private void UiElementOnManipulationStarting(object sender, ManipulationStartingRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("ManipulationStarting", _element, string.Format("{0}, {1}, {2}", e.Container.GetType().Name, e.Mode, e.Pivot.Center)));
        }

        private void UiElementOnManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("ManipulationStarted", _element, string.Format("{0}, {1}, {2}", e.Container.GetType().Name, e.Position, e.Cumulative)));
        }

        private void UiElementOnManipulationInertiaStarting(object sender, ManipulationInertiaStartingRoutedEventArgs manipulationInertiaStartingRoutedEventArgs)
        {
            EventOccured.Fire(this, new XamlEvent("ManipulationInertiaStarting", _element, string.Empty));
        }

        private void UiElementOnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs manipulationDeltaRoutedEventArgs)
        {
            EventOccured.Fire(this, new XamlEvent("ManipulationDelta", _element, string.Empty));
        }

        private void UiElementOnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs manipulationCompletedRoutedEventArgs)
        {
            EventOccured.Fire(this, new XamlEvent("ManipulationCompleted", _element, string.Empty));
        }

        private void UiElementOnKeyUp(object sender, KeyRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("KeyUp", _element, string.Format("{0}, {1}", e.Key, e.KeyStatus)));
        }

        private void UiElementOnKeyDown(object sender, KeyRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("KeyDown", _element, string.Format("{0}, {1}", e.Key, e.KeyStatus)));
        }

        private void UiElementOnHolding(object sender, HoldingRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("Holding", _element, string.Format("{0}, {1}", e.HoldingState, e.PointerDeviceType)));
        }

        private void UiElementOnDrop(object sender, DragEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("Drop", _element, string.Format("{0}, {1}", e.GetPosition(_element.Element), e.Data)));
        }

        private void UiElementOnDragOver(object sender, DragEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("DragOver", _element, string.Format("{0}, {1}", e.GetPosition(_element.Element), e.Data)));
        }

        private void UiElementOnDragLeave(object sender, DragEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("DragLeave", _element, string.Format("{0}, {1}", e.GetPosition(_element.Element), e.Data)));
        }

        private void UiElementOnDragEnter(object sender, DragEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("DragEnter", _element, string.Format("{0}, {1}", e.GetPosition(_element.Element), e.Data)));
        }

        private void UiElementOnPointerEntered(object sender, PointerRoutedEventArgs e)
        {
            EventOccured.Fire(this, new XamlEvent("PointerEntered", _element, string.Format("{0}, {1}", e.GetCurrentPoint(_element.Element).Position, e.Pointer.PointerDeviceType)));
        }
    }
}
